package com.inkyi.assistant.app.utils;

import net.miginfocom.swing.MigLayout;

import java.util.StringJoiner;

public class MigLayoutHelper {

    /**
     * @param layoutConstraints 设置全局的布局约束，
     *                          fill: 强制所有组件填充其所在的单元格
     *                          insets <top> <left> <bottom> <right>: 设置默认的内边距。insets 10 表示四边均为10。
     *                          gapy <top gap> <bottom gap> 和 gapx <left gap> <right gap>: 设置默认的垂直和水平间隙
     *                          align <alignment>: 设置默认的对齐方式，如align center center
     *                          hidemode <mode>: 设置隐藏模式，当一个组件的大小不足以显示其内容时的行为。
     *                          debug: 开启调试模式，可以在运行时看到布局网格。
     *                          wrap + 数字：指定默认在第几个组件后进行换行，如： wrap 2 表示在第二个组件后进行分行。
     * @param colConstraints    列的约束，每一列可以有不同的约束，指定 横向单元格 的各个属性。每个单元格的属性用[]括起来。如[][][]表示一行有三个单元格。
     *                          各单元格可以定制的属性如下：
     *                          <width>,列的首选宽度。
     *                          <width>!,固定宽度，不会随着容器的大小变化而改变。40!: 表明该列的单元格宽度固定为40
     *                          <width>%,列的宽度占的百分比。40%:表示该组件占用整个容器的百分比
     *                          <min-width>:<width>:<max-width> ,10:30:40：表明该列的单元格宽度最小为10、最佳为30、最大为40
     *                          ::40,表明该单元格最大值为４０。其它也可以是:30: 或者：30::等。
     *                          max <max-width>,列的最大宽度。
     *                          min <min-width>,列的最小宽度。
     *                          shrink,列可以缩小以适应较小的容器。
     *                          grow,x 列可以伸缩以填充可用空间。注意如果此处不添加grow，那么在添加组件的时候使用growx会没有效果。
     *                          center/right/left,指定该组件在水平方向的对齐方式
     *                          同时，也可以指定各个单元格之间的间隔：[]30[][]说明第一个和第二个单元格之间相隔30（该参数不会计算单元格）
     * @param rowConstraints    行的约束，每一行的不同约束，指定纵向的单元格的各个属性。
     *                          <height>: 行的首选高度。
     *                          <height>!: 固定高度，不会随着容器的大小变化而改变。
     *                          grow: 行可以伸缩以填充可用空间。
     *                          shrink: 行可以缩小以适应较小的容器。
     *                          max <max-height>: 行的最大高度。
     *                          min <min-height>: 行的最小高度。
     *                          ::: ：指定高度属性，与第二个参数意义一致。
     *                          top/bottom/center：指定在垂直方向的对齐方式。
     * @return
     */
    public static MigLayout create(String layoutConstraints, String colConstraints, String rowConstraints) {
        return new MigLayout(layoutConstraints, colConstraints, rowConstraints);
    }

    public static MigLayout create(String layoutConstraints) {
        return new MigLayout(layoutConstraints, "", "");
    }

    public static MigLayout create() {
        return new MigLayout("", "", "");
    }

    public static MigLayoutConstraints constraints() {
        return new MigLayoutConstraints();
    }

    public static class MigLayoutConstraints {
        private StringJoiner constraints = new StringJoiner(",");

        private boolean isEmpty(Object[] params) {
            return params == null || params.length == 0;
        }

        /**
         * 横跨多少行/列
         *
         * @param num 全国矿工工会
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints span(Integer... num) {
            if (isEmpty(num)) {
                constraints.add("span");
            } else if (num.length == 1) {
                constraints.add("span " + num[0]);
            } else if (num.length == 2) {
                constraints.add("span " + num[0] + num[1]);
            }
            return this;
        }

        /**
         * 分组
         *
         * @param group 组名
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints sg(String group) {
            constraints.add("sg " + group);
            return this;
        }

        public MigLayoutConstraints split(Integer num) {
            if (num != null && num > 0) {
                constraints.add("split " + num);
            } else {
                constraints.add("split");
            }
            return this;
        }

        /**
         * 组件应该尽可能地占用可用的空间
         * 如果组件所在的行或列有多余的空间，那么这个组件将会扩大以填满这些空间。
         * 当一个组件被设置了 push 时，它会尝试比其他没有设置 push 的组件占据更多的空间。
         *
         * @param coordinate 协调 x or y
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints push(String... coordinate) {
            if (isEmpty(coordinate)) {
                constraints.add("push");
            } else if (coordinate.length == 2) {
                constraints.add("push" + coordinate[0]);
                constraints.add("push" + coordinate[1]);
            } else {
                constraints.add("push" + coordinate[0]);
            }
            return this;
        }

        /**
         * 充满整个单元格
         * 组件应该尽可能地占用可用的空间，增长到该行剩余空间最后
         * 与Push不同的是，会影响整个容器（例如 JPanel）的大小。
         * 当一个组件被设置了 grow 时，容器本身将会增长以适应这个组件的需求。
         * 这意味着如果一个具有 grow 约束的组件需要更多的空间，那么容器将会增大以满足这一需求。
         *
         * @param coordinate 协调 x or y
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints grow(String... coordinate) {
            if (isEmpty(coordinate)) {
                constraints.add("grow");
            } else if (coordinate.length == 2) {
                constraints.add("grow" + coordinate[0]);
                constraints.add("grow" + coordinate[1]);
            } else {
                constraints.add("grow" + coordinate[0]);
            }
            return this;
        }

        /**
         * 对齐方式-左对齐
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints left() {
            constraints.add("left");
            return this;
        }

        /**
         * 对齐方式，后面可以接left right center
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints align() {
            constraints.add("align ");
            return this;
        }



        /**
         * 水平对齐方式-右对齐
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints right() {
            constraints.add("right");
            return this;
        }


        /**
         * 水平/垂直对齐方式-中心对齐
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints center() {
            constraints.add("center");
            return this;
        }

        /**
         * 垂直对齐方式-顶部
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints top() {
            constraints.add("top");
            return this;
        }

        /**
         * 垂直对齐方式-底部
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints bottom() {
            constraints.add("bottom");
            return this;
        }


        /**
         * 换行 , wrap + 数字：指定默认在第几个组件后进行换行，如： wrap 2 表示在第二个组件后进行分行
         *
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints wrap() {
            constraints.add("wrap");
            return this;
        }

        /**
         * 自定义
         *
         * @param custom 自定义
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints custom(String... custom) {
            if (isEmpty(custom)) {
                return this;
            } else {
                for (String c : custom) {
                    constraints.add(c);
                }
            }
            return this;
        }


        /**
         * 默认与边界的距离
         * insets + 数字：指定默认与边界的距离，有两种方式：insets 10 表示四边均为10，insets 1 2 3 4 分别指示顶部、左侧、下部、右侧距离
         *
         * @param size 大小
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints insets(Integer... size) {
            if (isEmpty(size)) {
                constraints.add("insets");
            } else if (size.length == 1) {
                constraints.add("insets " + size[0]);
            } else if (size.length == 2) {
                constraints.add("insets " + size[0] + " " + size[1]);
            } else if (size.length == 4) {
                constraints.add("insets " + size[0] + " " + size[1] + " " + size[2] + " " + size[3]);
            }
            return this;
        }


        /**
         * 组件在布局中的位置,索引从0开始
         * cell 0 0 -> cell 列 行
         * cell 0 0 2 1 -> cell 列 行 宽 高 (宽高是指跨越的宽度和高度，比如宽是2，就代表占中两个格子)
         *
         * @param idx 位置
         * @return {@link MigLayoutConstraints }
         */
        public MigLayoutConstraints cell(Integer... idx) {
            if (idx.length == 2) {
                constraints.add("cell " + idx[0] + " " + idx[1]);
            } else if (idx.length == 4) {
                constraints.add("cell " + idx[0] + " " + idx[1] + " " + idx[2] + " " + idx[3]);
            } else {
                throw new IllegalArgumentException("cell 参数个数不正确");
            }
            return this;
        }


        /**
         * hidemode 属性控制 当组件 不再可见 时如何隐藏它们
         * 0 - 默认值。表示不可见组件的处理方式将与可见组件完全相同。
         * 1 - 组件的大小（如果不可见）将设置为 0， 0。
         * 2 - 组件的大小（如果不可见）将设置为 0、0，并且其周围的间隙也将设置为 0。
         * 3 - 不可见的组件根本不会参与布局，例如，它不会占用网格单元。
         *
         * @param mode 模式
         * @return {@link MigLayoutConstraints}
         */
        public MigLayoutConstraints hidemode(Integer mode) {
            if (mode != null) {
                constraints.add("hidemode " + mode);
            }
            return this;
        }

        /**
         * 宽度
         * 可以写作：w 150 或者 width 150
         *
         * @param size 大小
         * @return {@link MigLayoutConstraints }
         */
        public MigLayoutConstraints width(Integer size) {
            if (size != null) {
                constraints.add("w " + size);
            }
            return this;
        }


        public String build() {
            return constraints.toString();
        }
    }

}
